package com.wzapp.sitposture.authentication.util;

import com.wzapp.sitposture.common.util.MD5Util;
import org.springframework.security.authentication.encoding.MessageDigestPasswordEncoder;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 功能:md5加密 <br/>
 *
 * @author ql
 * @version 0.4
 * @create 2018-06-07 15:25
 **/
public class Md5PasswordEncoder extends MessageDigestPasswordEncoder {

    public Md5PasswordEncoder() {
        super("MD5");
    }

    public Md5PasswordEncoder(String algorithm) {
        super(algorithm);
    }

    public Md5PasswordEncoder(String algorithm, boolean encodeHashAsBase64) throws IllegalArgumentException {
        super(algorithm, encodeHashAsBase64);
    }

    /**
     * 功能:md5加密 <br/>
     *
     * @param rawPass
     * @return java.lang.String
     * @author ql
     * @create 2018-06-07 15:34
     **/
    public String encodePassword(String rawPass) {
        return encodePassword(rawPass.getBytes());
    }

    /**
     * Encodes the rawPass using a MessageDigest. If a salt is specified it will be merged
     * with the password before encoding.
     *
     * @param rawPass The plain text password
     * @param salt    The salt to sprinkle
     * @return Hex string of password digest (or base64 encoded string if
     * encodeHashAsBase64 is enabled.
     */
    @Override
    public String encodePassword(String rawPass, Object salt) {
        try {
            if (null == salt) {
                return encodePassword(rawPass);
            }
            MessageDigest md = MessageDigest.getInstance("MD5");
            //计算MD5函数
            md.update(salt.toString().getBytes());
            return encodeHex(md.digest(rawPass.getBytes()));
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
//        return encodePassword(rawPass.getBytes(), salt.toString().getBytes());
    }

    /**
     * Takes a previously encoded password and compares it with a rawpassword after mixing
     * in the salt and encoding that value
     *
     * @param encPass previously encoded password
     * @param rawPass plain text password
     * @param salt    salt to mix into password
     * @return true or false
     */
    @Override
    public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
        String pass1 = encPass;
        //此处验证需要对传入密码再md5加密，根据算法md5(rawpass+salt)
        String pass2 = MD5Util.encrypt(rawPass,salt.toString());

        return PasswordEncoderUtil.equals(pass1, pass2);
    }

    private static String encodePassword(byte[] source) {
        try {
            return encodeHex(MessageDigest.getInstance("MD5").digest(source));
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

    private static String encodePassword(byte[] source, byte[] salt) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            //计算MD5函数
            md.update(salt);
            return encodeHex(md.digest(source));
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

    private static String encodeHex(byte[] bytes) {
        StringBuffer buffer = new StringBuffer(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            if (((int) bytes[i] & 0xff) < 0x10) {
                buffer.append("0");
            }
            buffer.append(Long.toString((int) bytes[i] & 0xff, 16));
        }
        return buffer.toString();
    }
}

